#ifndef PHYSIC_H
#define PHYSIC_H

#include "entity/entity.h"
#include "loader/b2dJson.h"
#include "../sleek/node/billboard/billboard.h"

namespace interne
{
    class GameCore;
    class SleekDebugDraw : public b2Draw
    {
        public:
            SleekDebugDraw(sleek::texture::draw *mom) : context(mom)
            {
                offset = b2Vec2(0,0);
                SetFlags(e_aabbBit | e_shapeBit);
            }

            virtual void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
            {
                glColor4f(color.r, color.g, color.b, 0.75f);
                glBegin(GL_LINE_LOOP);
                for (int32 i = 0; i < vertexCount; ++i)
                    glVertex3f(vertices[i].x+offset.x, vertices[i].y+offset.y,0.1);
                glEnd();
            }
            virtual void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
            {
                glEnable(GL_BLEND);
                glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                glColor4f(color.r, color.g, color.b, 0.75f);
                glBegin(GL_TRIANGLE_FAN);
                for (int32 i = 0; i < vertexCount; ++i)
                {
                    glVertex3f(vertices[i].x+offset.x, vertices[i].y+offset.y,0.1);
                }
                glEnd();
                glDisable(GL_BLEND);

                glColor4f(color.r, color.g, color.b, 1.0f);
                glBegin(GL_LINE_LOOP);
                for (int32 i = 0; i < vertexCount; ++i)
                    glVertex3f(vertices[i].x+offset.x, vertices[i].y+offset.y,0.1);
                glEnd();
            }
            virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
            {
                const float32 k_segments = 16.0f;
                const float32 k_increment = 2.0f * b2_pi / k_segments;
                float32 theta = 0.0f;
                glColor4f(color.r, color.g, color.b, 0.75f);
                glBegin(GL_LINE_LOOP);
                for (int32 i = 0; i < k_segments; ++i)
                {
                    b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
                    glVertex3f(v.x+offset.x, v.y+offset.y,0.1);
                    theta += k_increment;
                }
                glEnd();
            }
            virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color)
            {
                const float32 k_segments = 16.0f;
                const float32 k_increment = 2.0f * b2_pi / k_segments;
                float32 theta = 0.0f;
                glEnable(GL_BLEND);
                glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                glColor4f(color.r, color.g, color.b, 0.5f);
                glBegin(GL_TRIANGLE_FAN);
                for (int32 i = 0; i < k_segments; ++i)
                {
                    b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
                    glVertex3f(v.x+offset.x, v.y+offset.y,0.1);
                    theta += k_increment;
                }
                glEnd();
                glDisable(GL_BLEND);

                theta = 0.0f;
                glColor4f(color.r, color.g, color.b, 1.0f);
                glBegin(GL_LINE_LOOP);
                for (int32 i = 0; i < k_segments; ++i)
                {
                    b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
                    glVertex3f(v.x+offset.x, v.y+offset.y,0.1);
                    theta += k_increment;
                }
                glEnd();

                b2Vec2 p = center + radius * axis;
                glBegin(GL_LINES);
                glVertex3f(center.x+offset.x, center.y+offset.y,0.1);
                glVertex3f(p.x+offset.x, p.y+offset.y,0.1);
                glEnd();
            }
            virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
            {
                glColor4f(color.r, color.g, color.b, 0.75f);
                glBegin(GL_LINES);
                glVertex3f(p1.x+offset.x, p1.y+offset.y,0.1);
                glVertex3f(p2.x+offset.x, p2.y+offset.y,0.1);
                glEnd();
            }
            virtual void DrawTransform(const b2Transform& xf)
            {
                b2Vec2 p1 = xf.p, p2;
                const float32 k_axisScale = 0.4f;
                glBegin(GL_LINES);

                glColor3f(1.0f, 0.0f, 0.0f);
                glVertex3f(p1.x, p1.y,0.1);
                p2 = p1 + k_axisScale * xf.q.GetXAxis();
                glVertex3f(p2.x+offset.x, p2.y+offset.y,0.1);

                glColor3f(0.0f, 1.0f, 0.0f);
                glVertex3f(p1.x, p1.y,0.1);
                p2 = p1 + k_axisScale * xf.q.GetYAxis();
                glVertex3f(p2.x+offset.x, p2.y+offset.y,0.1);

                glEnd();
            }
        protected:
            b2Vec2 offset;
            sleek::texture::draw *context;
    };
    class Physic
    {
        public:
            Physic(GameCore*);
            virtual ~Physic();

            virtual void setWorld(b2World*);
            virtual void createPlayer(Entity*);
            virtual void createDynamicBox(Entity*);
            virtual void createStaticBox(Entity*);
            virtual void createVirtual(Entity*);

            void debug();
            void step();

            b2World *world;
        protected:
            virtual void createBox(Entity*, b2BodyDef, sleek::core::math::vector2du);
        private:
            b2dJson import;
            sleek::core::u32 timespec, current;
            sleek::core::math::timer time_stamp;
            GameCore *core;
    };
}

#endif // PHYSIC_H
